package com.nullpointer.xchatfinal.fragment;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;

import com.nullpointer.xchatfinal.MainActivity;
import com.nullpointer.xchatfinal.R;
import com.nullpointer.xchatfinal.adapter.GroupAdapter;
import com.nullpointer.xchatfinal.fragment.CreateGroupDialogFragment.OnCreateGroupDialogFragment;
import com.nullpointer.xchatfinal.libs.GridViewWithHeaderAndFooter;
import com.nullpointer.xchatfinal.object.ChatType;
import com.nullpointer.xchatfinal.object.GroupChat;
import com.nullpointer.xchatfinal.object.GroupMessageContent;
import com.nullpointer.xchatfinal.object.MessageContent;
import com.nullpointer.xchatfinal.object.OnJoinRoomListener;
import com.nullpointer.xchatfinal.object.PrivateMessageContent;
import com.nullpointer.xchatfinal.object.TargetChat;
import com.nullpointer.xchatfinal.object.User;
import com.nullpointer.xchatfinal.object.MessageContent.MsgType;
import com.nullpointer.xchatfinal.service.ChatService;
import com.nullpointer.xchatfinal.utils.DataManager;
import com.nullpointer.xchatfinal.utils.Error;
import com.nullpointer.xchatfinal.utils.InfoText;
import com.nullpointer.xchatfinal.utils.KiraGameLog;
import com.nullpointer.xchatfinal.utils.Error.ErrorCode;
import com.quickblox.chat.QBChatService;
import com.quickblox.chat.model.QBDialog;
import com.quickblox.chat.model.QBDialogType;
import com.quickblox.core.QBEntityCallbackImpl;
import com.quickblox.core.request.QBRequestGetBuilder;

public class GroupsFragment extends Fragment {

	private GridViewWithHeaderAndFooter gvGroups;
	private List<GroupChat> groupData = new ArrayList<GroupChat>();
	private GroupAdapter groupAdapter;
	private int page = 1;
	private final int SIZE_PER_PAGE = 10;
	private boolean isLoadDone = true;
	private boolean canLoadMore = false;
	private View footerView;

	public static GroupsFragment newInstance() {
		GroupsFragment f = new GroupsFragment();
		return f;
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View view = inflater
				.inflate(R.layout.fragment_groups, container, false);
		footerView = inflater.inflate(R.layout.view_item_load_more, null);
		findViewIds(view);
		init();
		setEvent();
		return view;
	}

	private void init() {
		gvGroups.addFooterView(footerView);
		footerView.setVisibility(View.GONE);
		groupAdapter = new GroupAdapter(getActivity(), groupData);
		gvGroups.setAdapter(groupAdapter);
		refreshData();
	}

	private void getGroups(int page) {
		showLoadingAnimation();
		QBRequestGetBuilder requestBuilder = new QBRequestGetBuilder();
		requestBuilder.setPagesSkip((page - 1) * SIZE_PER_PAGE);
		requestBuilder.setPagesLimit(SIZE_PER_PAGE);
		requestBuilder.sortDesc("type");
		// requestBuilder.addParameter("data[class_name]", "Advert");

		QBChatService.getChatDialogs(null, requestBuilder,
				new QBEntityCallbackImpl<ArrayList<QBDialog>>() {
					@Override
					public void onSuccess(ArrayList<QBDialog> dialogs,
							Bundle params) {
						KiraGameLog.d("get dialogs: " + dialogs);
						if (dialogs == null || dialogs.size() == 0) {
							isLoadDone = true;
							canLoadMore = false;
							hideLoadingAnimation();
						} else {
							for (QBDialog qbDialog : dialogs) {
								GroupChat groupChat = new GroupChat();
								groupChat.setName(qbDialog.getName());
								groupChat.setAvatarURL(qbDialog.getPhoto());
								groupChat.setGroupJID(qbDialog.getRoomJid());
								groupChat.setNumMember(qbDialog.getOccupants()
										.size());
								qbDialog.setDialogId(qbDialog.getDialogId());
								if (qbDialog.getType() == QBDialogType.PUBLIC_GROUP) {
									groupChat.setPublicGroup(true);
								} else {
									groupChat.setPublicGroup(false);
								}
								groupData.add(groupChat);
							}
							groupAdapter.notifyDataSetChanged();
							hideLoadingAnimation();
							isLoadDone = true;
							if (dialogs.size() < SIZE_PER_PAGE) {
								canLoadMore = false;
							} else {
								canLoadMore = true;
							}
						}
					}

					@Override
					public void onError(List<String> errors) {
						KiraGameLog.d("get dialogs " + errors);
						hideLoadingAnimation();
						isLoadDone = true;
						canLoadMore = false;
					}
				});
	}

	public void refreshData() {
		isLoadDone = true;
		canLoadMore = false;
		page = 1;
		clearUserData();
		showLoadingInfo();
		getGroups(page);
	}

	private void moreLoad() {
		if (!isLoadDone) {
			return;
		}
		KiraGameLog.d("load more with page " + page);
		isLoadDone = false;
		page++;
		showLoadMoreView();
		getGroups(page);
	}

	private void setEvent() {
		gvGroups.setOnScrollListener(new OnScrollListener() {

			@Override
			public void onScrollStateChanged(AbsListView view, int scrollState) {

			}

			@Override
			public void onScroll(AbsListView view, int firstVisibleItem,
					int visibleItemCount, int totalItemCount) {
				if (view.getLastVisiblePosition() >= totalItemCount - 1) {
					if (!canLoadMore) {
						return;
					}
					moreLoad();
				}
			}
		});
	}

	private void findViewIds(View view) {
		gvGroups = (GridViewWithHeaderAndFooter) view
				.findViewById(R.id.gv_rooms);
	}

	private void clearUserData() {
		groupData.clear();
		groupAdapter.notifyDataSetChanged();
	}

	private void showLoadMoreView() {
		footerView.setVisibility(View.VISIBLE);
		gvGroups.post(new Runnable() {
			@Override
			public void run() {
				gvGroups.tryToScrollToBottomSmoothly(100);
			}
		});
	}

	private void showLoadingAnimation() {
		try {
			((MainActivity) getActivity()).startRefeshAnimation();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void showLoadingInfo() {
		try {
			((MainActivity) getActivity()).showInfo("loading data...", true);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void hideLoadingAnimation() {
		try {
			((MainActivity) getActivity()).stopRefeshAnimation();
			((MainActivity) getActivity()).hideInfo();
		} catch (Exception e) {
			e.printStackTrace();
		}
		footerView.setVisibility(View.GONE);
	}

	public void addGroup() {
		try {
			final CreateGroupDialogFragment dialog = new CreateGroupDialogFragment();
			dialog.setOnCreateGroupDialogFragment(new OnCreateGroupDialogFragment() {

				@Override
				public void onCreated(QBDialog qbDialog) {
					updateListGroup(qbDialog);
					joinChat(qbDialog);
					notifyMemberJoinGroup(qbDialog, qbDialog.getOccupants());
				}
			});
			FragmentTransaction transaction = getActivity()
					.getSupportFragmentManager().beginTransaction();
			transaction.add(dialog, "CreateGroupDialogFragment");
			transaction.commitAllowingStateLoss();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	protected void sendCreateNewGroupMessageToGroup(final String roomJID,
			final String groupName) {
		User currentUser = DataManager.getInstance(getActivity())
				.getCurrentUser();
		String currentUserName = currentUser.getName();
		MessageContent msg = new MessageContent(currentUser.getUserID());
		msg.setName(currentUserName);
		String content = currentUserName + " create this group";
		msg.setContent(content);
		msg.setAvatarID(currentUser.getUserInfo().getAvatarID());
		msg.setMsgType(MsgType.UPDATE_GROUP_INFO);

		GroupMessageContent groupMessageContent = new GroupMessageContent();
		groupMessageContent.setMessageContent(msg);
		groupMessageContent.setFromGroupJID(roomJID);
		groupMessageContent.setFromGroupName(groupName);
		ChatService.getInstance().sendMessageChatGroup(groupMessageContent,
				null);
	}

	protected void notifyMemberJoinGroup(QBDialog qbDialog,
			ArrayList<Integer> occupants) {
		GroupChat groupChat = new GroupChat();
		groupChat.setName(qbDialog.getName());
		groupChat.setGroupJID(qbDialog.getRoomJid());
		for (Integer userID : occupants) {
			PrivateMessageContent privateMessageContent = new PrivateMessageContent(
					getActivity(), groupChat.toJson(), MsgType.ADD_GROUP,
					Integer.toString(userID));
			ChatService.getInstance().sendMessagePrivate(privateMessageContent,
					null);

		}
	}

	protected void joinChat(QBDialog qbDialog) {
		ChatService.getInstance().joinroom(qbDialog.getRoomJid(),
				qbDialog.getName(), joinRoomListener);
	}

	protected void updateListGroup(QBDialog qbDialog) {
		GroupChat groupChat = new GroupChat();
		groupChat.setName(qbDialog.getName());
		groupChat.setAvatarURL(qbDialog.getPhoto());
		groupChat.setGroupJID(qbDialog.getRoomJid());
		groupChat.setNumMember(qbDialog.getOccupants().size());
		qbDialog.setDialogId(qbDialog.getDialogId());
		if (qbDialog.getType() == QBDialogType.PUBLIC_GROUP) {
			groupChat.setPublicGroup(true);
		} else {
			groupChat.setPublicGroup(false);
		}
		groupData.add(0, groupChat);
		groupAdapter.notifyDataSetChanged();
	}

	OnJoinRoomListener joinRoomListener = new OnJoinRoomListener() {

		@Override
		public void onPreJoinRoom() {
			KiraGameLog.d("onPreJoinRoom");
			((Activity) getActivity()).runOnUiThread(new Runnable() {
				@Override
				public void run() {
					showOnPreJoinRoomNotice();
				}
			});

		}

		@Override
		public void onJoinRoomSuccessed(final String roomJID,
				final String groupName) {
			KiraGameLog.d("onJoinRoomSuccessed");
			((Activity) getActivity()).runOnUiThread(new Runnable() {
				@Override
				public void run() {
					doOnJoinRoomSuccessed(roomJID, groupName);
				}
			});

		}

		@Override
		public void onJoinRoomFailed(final ErrorCode errorCode,
				final String roomJID, final String groupName) {
			KiraGameLog.d("onJoinRoomFailed");

			((Activity) getActivity()).runOnUiThread(new Runnable() {
				@Override
				public void run() {
					showJoinRoomErrorNotice(errorCode, roomJID, groupName);
				}
			});
		}
	};

	private void showJoinRoomErrorNotice(ErrorCode errorCode,
			final String roomJID, final String groupName) {
		switch (errorCode) {
		case CONNECT_SERVER_ERROR:
			try {
				((MainActivity) getActivity())
						.showConnectServerError(Error.ErrorInfo[errorCode
								.ordinal()]);
			} catch (Exception e) {
				e.printStackTrace();
			}
			break;

		case JOIN_ROOM_FAIL_NOT_MEMBER:
			try {
				((MainActivity) getActivity()).showNotice(false,
						Error.ErrorInfo[errorCode.ordinal()], "RETRY",
						new OnClickListener() {

							@Override
							public void onClick(View v) {
								ChatService.getInstance().joinroom(roomJID,
										groupName, joinRoomListener);
							}
						});
			} catch (Exception e) {
				e.printStackTrace();
			}
			break;

		case JOIN_ROOM_FAIL:
			try {
				((MainActivity) getActivity()).showNotice(false,
						Error.ErrorInfo[errorCode.ordinal()], "RETRY",
						new OnClickListener() {

							@Override
							public void onClick(View v) {
								ChatService.getInstance().joinroom(roomJID,
										groupName, joinRoomListener);
							}
						});
			} catch (Exception e) {
				e.printStackTrace();
			}
			break;

		default:
			break;
		}

	}

	protected void doOnJoinRoomSuccessed(final String roomJID,
			final String groupName) {
		showChat(roomJID, groupName);
		// send message create new group to room
		sendCreateNewGroupMessageToGroup(roomJID, groupName);
	}

	protected void showChat(String roomJID, String groupName) {
		try {
			TargetChat targetChat = new TargetChat(ChatType.CHAT_GROUP,
					roomJID, groupName);
			((MainActivity) getActivity()).showChat(targetChat);
			((MainActivity) getActivity()).hideNotice();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void showOnPreJoinRoomNotice() {
		try {
			((MainActivity) getActivity()).showNotice(true,
					InfoText.JOINING_GROUP, null, null);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
